/*
 * Created by SharpDevelop.
 * User: David
 * Date: 2006-12-16
 * Time: 02:52
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */

using System;
using System.Collections.Generic;

using tools;

using Labb4.Main;
using Labb4.Rules;
using Labb4.Pooman.Misc;

namespace Labb4.Pooman.Cards
{
	/// <summary>
	/// A hand, wrapping a CardPile and adding some logical playing functionality
	/// </summary>
	public class Hand : IBasicHand
	{
		#region members
		
		/// <summary>
		/// The CardPile of this hand
		/// </summary>
		private CardPile			m_Cards;
		/// <summary>
		/// The current rules
		/// </summary>
		private PoomanRules			m_Rules;
		/// <summary>
		/// The input manager
		/// </summary>
		private InputManager		m_InputManager;
		
		#endregion
		
		#region constructors
		
		/// <summary>
		/// Constructor, intializes members
		/// </summary>
		public Hand()
		{
			m_Cards = new CardPile();
			m_Rules = PoomanRules.Instance;
			m_InputManager = InputManager.Instance;
		}
		
		#endregion
		
		#region methods
		
		/// <summary>
		/// Selects or unselects all cards on hand
		/// </summary>
		/// <param name="selected">True to select all cards, false to unselect them</param>
		public void SelectAllCards(bool selected)
		{
			m_Cards.SelectAllCards(selected);
		}
		
		/// <summary>
		/// Counts the number of currently selected cards on hand
		/// </summary>
		/// <returns>The number of currently selected cards on hand</returns>
		public int SelectedCards()
		{
			int selected = 0;
			
			foreach(Card it in m_Cards)
			{
				if(it.Selected)
				{
					selected++;
				}
			}
			
			return selected;
		}
		
		/// <summary>
		/// Saves this hand to a List of string
		/// </summary>
		/// <param name="fileContent">The List of string to save this hand to</param>
		/// <param name="player">The name of the player holding this hand</param>
		/// <param name="hand">The name of this hand, as seen from the players perspective</param>
		/// <param name="displayType">The animation to show for this card's graphical representation</param>
		public void Save(List<string> fileContent, string player, string hand, string displayType)
		{
			m_Cards.Save(fileContent, player + hand, displayType);
		}
		
		/// <summary>
		/// Loads a hand from a file
		/// </summary>
		/// <param name="config">The file to load from</param>
		/// <param name="player">The name of the player holding this hand</param>
		/// <param name="hand">The name of this hand, as seen from the players perspective</param>
		public void Load(Config config, string player, string hand)
		{
			m_Cards.Load(config, player + hand);
		}
		
		#endregion
		
		#region implemented interface methods
		
		/// <summary>
		/// Highlights a card at a given position, if this card is playable in the current context
		/// </summary>
		/// <param name="x">The x coordinate of the card, relative to the screen</param>
		/// <param name="y">The y coordinate of the card, relative to the screen</param>
		public void HighlightCard(ref int x, ref int y)
		{
			bool foundCardToHighlight = false;
			
			for(int i = m_Cards.Count - 1; i > (-1); i--)
			{
				m_Cards[i].HighlightCard(false);
				
				if(!foundCardToHighlight)
				{
					if(m_Cards[i].HasPoint(ref x, ref y))
					{
						foundCardToHighlight = true;
						
						if(IsSelectableInCurrentContext(m_Cards[i]))
						{
							m_Cards[i].HighlightCard(true);
							string trump = "";
							
							if(m_Rules.CurrentTrump != null)
							{
								if(m_Cards[i].SuitOfCard == m_Rules.CurrentTrump.TrumpSuit)
								{
									trump = " (trump)";
								}
							}
							
							m_InputManager.StatusString = (m_Cards[i].ToString() + trump);
						}
						else
						{
							if(SelectedCards() > 0)
							{
								m_InputManager.StatusString = m_Cards[i].ToString() + " can not be selected together with those cards that are allready selected.";
							}
							else
							{
								m_InputManager.StatusString = m_Cards[i].ToString() + " does not top the highest card currently on the table.";
							}
						}
					}
				}
			}
		}
		
		/// <summary>
		/// Selects a card at a given screen coordinate
		/// </summary>
		/// <param name="x">The x coordinate where a card should be selected, relative to the screen</param>
		/// <param name="y">The y coordinate where a card should be selected, relative to the screen</param>
		public void SelectCard(ref int x, ref int y)
		{
			for(int i = m_Cards.Count - 1; i > (-1); i--)
			{
				//TODO
				//which operation is more expencive?
				//evaluating selectable cards, or checking if the picture has the point?
				//the order of the two following if statements have no logical importance
				//but the order may affect the fps
				
				//TODO make "hidden" parts of cards unavailable for selection
				if(IsSelectableInCurrentContext(m_Cards[i]))
				{
					if(m_Cards[i].HasPoint(ref x, ref y))
					{
						m_Cards[i].SelectCard(!m_Cards[i].Selected);
						i = -1;
					}
				}
			}
		}
		
		/// <summary>
		/// Gets all the currently selected cards on hand
		/// </summary>
		/// <returns>A CardPile with all the currently selected cards</returns>
		public CardPile GetSelectedCards()
		{
			CardPile cardPile = new CardPile();
			
			foreach(Card it in m_Cards)
			{
				if(it.Selected)
				{
					cardPile.Add(it);
				}
			}
			
			m_Cards.Remove(cardPile);
			
			return cardPile;
		}
		
		/// <summary>
		/// Checks that a selected card is still selectable in the current context
		/// </summary>
		public void CheckAllSelectedCards()
		{
			CardPile selectable = GetSelectableCards();
			
			foreach(Card it in m_Cards)
			{
				if(it.Selected)
				{
					if(!selectable.Contains(it))
					{
						it.SelectCard(false);
					}
				}
			}
		}
		
		#endregion
		
		#region properties
		
		/// <summary>
		/// The cards on this hand (get)
		/// </summary>
		public CardPile Cards
		{
			get
			{
				return m_Cards;
			}
		}
		
		#endregion
		
		#region private methods
		
		/// <summary>
		/// Checks to see if a card is selectable in the current context
		/// </summary>
		/// <param name="card">The card to check</param>
		/// <returns>True if the card is currently selectable, otherwise false</returns>
		private bool IsSelectableInCurrentContext(Card card)
		{
			CardPile selectableCards = GetSelectableCards();
			
			return selectableCards.Contains(card);
		}
		
		/// <summary>
		/// Gets all the currently selectable cards on the hand and puts them in a CardPile
		/// </summary>
		/// <returns>A CardPile conatining all the currently selectable cards</returns>
		private CardPile GetSelectableCards()
		{
			return m_Rules.PlayableCards(m_Cards);
		}
		
		#endregion
	}
}
